﻿namespace SandScript.Wrappers
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;

    public class FileSystemWrapper : IFileSystemWrapper
    {
        public string GetRandomFileName()
        {
            return Path.GetRandomFileName();
        }

        public string GetTemporaryFolder()
        {
            var folder = Path.GetTempPath();
            var tempFolder = Path.Combine(folder, Path.GetRandomFileName());
            Directory.CreateDirectory(tempFolder);
            return tempFolder;
        }

        public void MoveFile(string sourceFilename, string destFilename)
        {
            File.Move(sourceFilename, destFilename);
        }

        public void CopyFile(string sourceFilename, string destFilename, bool overwrite = true)
        {
            File.Copy(sourceFilename, destFilename, overwrite);
        }

        public void SetFileAttributes(string fileName, FileAttributes attributes)
        {
            File.SetAttributes(fileName, attributes);
        }

        public void MoveDirectory(string sourceDirectory, string destDirectory)
        {
            if (!sourceDirectory.Equals(destDirectory, StringComparison.OrdinalIgnoreCase))
            {
                Directory.Move(sourceDirectory, destDirectory);
            }
        }

        public DateTime GetCreationTime(string path)
        {
            return File.GetCreationTime(path);
        }

        public DateTime GetLastAccessTime(string path)
        {
            return File.GetLastAccessTime(path);
        }

        public bool FileExists(string path)
        {
            return File.Exists(path);
        }

        public bool DirectoryExists(string path)
        {
            return Directory.Exists(path);
        }

        public void DeleteFile(string path)
        {
            if (this.FileExists(path))
            {
                File.Delete(path);
            }
        }

        public void DeleteDirectory(string path, bool recursive)
        {
            if (this.DirectoryExists(path))
            {
                Directory.Delete(path, recursive);
            }
        }

        public void CreateDirectory(string path)
        {
            Directory.CreateDirectory(path);
        }

        public IEnumerable<string> GetDirectories(string directory)
        {
            return Directory.GetDirectories(directory);
        }

        public string[] GetFiles(string path, string searchPattern, SearchOption searchOption)
        {
            return Directory.GetFiles(path, searchPattern, searchOption);
        }

        public Stream Open(string path)
        {
            return File.Open(path, FileMode.OpenOrCreate);
        }

        public Stream Open(string path, FileMode mode, FileAccess access)
        {
            return new FileStream(path, mode, access);
        }

        public void Save(string path, Stream stream)
        {
            using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                byte[] data = this.GetContent(stream);
                fs.Write(data, 0, data.Length);
            }
        }

        public void Save(string path, string contents)
        {
            File.WriteAllText(path, contents);
        }

        public byte[] GetContent(Stream stream)
        {
            byte[] data = new byte[stream.Length];
            int remaining = data.Length;
            int offset = 0;

            while (remaining > 0)
            {
                int read = stream.Read(data, offset, remaining);
                remaining -= read;
                offset += read;
            }

            stream.Position = 0;

            return data;
        }

        public string GetText(string path)
        {
            return File.ReadAllText(path);
        }

        public string[] GetLines(string path)
        {
            return File.ReadAllLines(path);
        }

        public bool TryResolvePath(string filePath, out string resolvedPath)
        {
            if (!string.IsNullOrWhiteSpace(filePath))
            {
                string tempPath;

                tempPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), filePath);

                if (this.FileExists(tempPath))
                {
                    resolvedPath = tempPath;
                    return true;
                }

                tempPath = Path.GetFullPath(filePath);

                if (this.FileExists(tempPath))
                {
                    resolvedPath = tempPath;
                    return true;
                }
            }

            resolvedPath = null;
            return false;
        }
    }
}
